package utils

import (
	"math"

	"github.com/shopspring/decimal"
)

type MyDecimal struct {
	value decimal.Decimal
}

// NewDecimal return d.
func NewDecimal(f float64) MyDecimal {
	return MyDecimal{value: decimal.NewFromFloat(f)}
}

// Add returns d + f.
func (d MyDecimal) Add(f float64) MyDecimal {
	d.value = d.value.Add(decimal.NewFromFloat(f))
	return d
}

// Sub returns d - f.
func (d MyDecimal) Sub(f float64) MyDecimal {
	d.value = d.value.Sub(decimal.NewFromFloat(f))
	return d
}

// Neg returns -d.
func (d MyDecimal) Neg() MyDecimal {
	d.value = d.value.Neg()
	return d
}

// Abs returns |d|.
func (d MyDecimal) Abs() MyDecimal {
	d.value = d.value.Abs()
	return d
}

// Mul returns d * f.
func (d MyDecimal) Mul(f float64) MyDecimal {
	d.value = d.value.Mul(decimal.NewFromFloat(f))
	return d
}

// Div returns d / f.
func (d MyDecimal) Div(f float64) MyDecimal {
	d.value = d.value.Div(decimal.NewFromFloat(f))
	return d
}

// Mod returns d % d2.
func (d MyDecimal) Mod(f float64) MyDecimal {
	d.value = d.value.Mod(decimal.NewFromFloat(f))
	return d
}

func (d MyDecimal) Round(places int32) MyDecimal {
	d.value = d.value.Round(places)
	return d
}

func (d MyDecimal) RoundFloor(places int32) MyDecimal {
	d.value = d.value.RoundFloor(places)
	return d
}

func (d MyDecimal) RoundUp(places int32) MyDecimal {
	d.value = d.value.RoundUp(places)
	return d
}

// Truncate 截断
func (d MyDecimal) Truncate(precision int32) MyDecimal {
	d.value = d.value.Truncate(precision)
	return d
}

// GetiItegerAndDecimal 获取小数的整数部分+小数部分
func (d MyDecimal) GetiItegerAndDecimal() (decimal.Decimal, decimal.Decimal) {
	intPart := d.value.Truncate(0)
	decimalPart := d.value.Sub(intPart)
	return intPart, decimalPart
}

func (d MyDecimal) Float64() float64 {
	f, exact := d.value.Float64()
	if !exact {
		Printf("MyDecimal Float64 no exact:%+v", d)
	}
	return f
}

// 向上取整
func (d MyDecimal) Ceil() int32 {
	f, exact := d.value.Float64()
	if !exact {
		Printf("MyDecimal Float64 no exact:%+v", d)
	}
	valI32 := int32(math.Ceil(f))
	return valI32
}

// 向下取整
func (d MyDecimal) Floor() int32 {
	f, exact := d.value.Float64()
	if !exact {
		Printf("MyDecimal Float64 no exact:%+v", d)
	}
	valI32 := int32(math.Floor(f))
	return valI32
}
